#![allow(dead_code)]
use crate::domain::CountNum;
use crate::domain::PermissionBean;
use crate::domain::RoleBean;
use crate::domain::RoleQueryRequest;
use crate::serviceimpl::init_db;
use crate::utils::string_util::is_digit;
use crate::utils::string_util::right_find_under_line;
use sqlx::Error;
use substring::Substring;

pub async fn activate_all_roles(ids:Vec<i64>) ->Result<u64, Error> {
	let app_state = init_db();
	let roles = &app_state.await.context.roles;
	let vecter_iterator = ids.iter();
	for role_id in vecter_iterator {
		let _ = roles.activate_role(*role_id).await;
	}
	Ok(0)
}

pub async fn activate_role(id:i64) ->Result<u64, Error> {
	let app_state = init_db();
	app_state.await.context.roles.activate_role(id).await
}

pub async fn add_role(role:RoleBean) ->Result<u64, Error> {
	let app_state = init_db();
	app_state.await.context.roles.add_role(role).await
}

pub async fn assign_permissions_to_role(role_id:i64,permission_ids:Vec<i64>) ->Result<u64, Error> {
	let app_state = init_db();
	let roles = &app_state.await.context.roles;
	for permission_id in permission_ids.iter() {
		roles.assign_permission_to_role(role_id,*permission_id).await.unwrap();
	}
	Ok(0)
}

pub async fn clone_all_roles(ids:Vec<i64>) ->Result<u64, Error> {
	let vecter_iterator = ids.iter();
	for role_id in vecter_iterator {
		let _ = clone_role(*role_id).await;
	}
	Ok(0)
}

pub async fn clone_role(id:i64) ->Result<u64, Error> {
	let mut role = find_role_by_id(id).await.unwrap();
	let role_name = find_role_indexed_name(role.role_name).await.unwrap();
	role.role_name = role_name;
	add_role(role).await
}

pub async fn count_search_roles_by_fields_records(role_query_request:RoleQueryRequest) ->Result<CountNum, Error> {
	let app_state = init_db();
	app_state.await.context.roles.count_search_roles_by_fields_records(role_query_request).await
}

pub async fn delete_all_roles(ids:Vec<i64>) ->Result<u64, Error> {
	let app_state = init_db();
	let roles = &app_state.await.context.roles;
	let vecter_iterator = ids.iter();
	for role_id in vecter_iterator {
		let _ = roles.delete_role(*role_id).await;
	}
	Ok(0)
}

pub async fn delete_role(id:i64) ->Result<u64, Error> {
	let app_state = init_db();
	app_state.await.context.roles.delete_role(id).await
}

pub async fn find_role_by_id(id:i64) ->Result<RoleBean, Error> {
	let app_state = init_db();
	app_state.await.context.roles.find_role_by_id(id).await
}

pub async fn find_role_by_role_name(role_name:String) ->Result<RoleBean, Error> {
	let app_state = init_db();
	app_state.await.context.roles.find_role_by_role_name(role_name).await
}

pub async fn list_active_role_permissions_using_role_id(role_id:i64) ->Result<Vec<PermissionBean>, Error> {
	let app_state = init_db();
	app_state.await.context.permissions.list_active_role_permissions_using_role_id(role_id).await
}

pub async fn list_active_roles() ->Result<Vec<RoleBean>, Error> {
	let app_state = init_db();
	app_state.await.context.roles.list_active_roles().await
}

pub async fn list_all_roles() ->Result<Vec<RoleBean>, Error> {
	let app_state = init_db();
	app_state.await.context.roles.list_all_roles().await
}

pub async fn list_available_active_role_permissions_using_role_id(role_id:i64) ->Result<Vec<PermissionBean>, Error> {
	let app_state = init_db();
	let permissions = &app_state.await.context.permissions;
	let mut all_permissions = permissions.list_active_permissions().await.unwrap();
	let current_permissions = list_active_role_permissions_using_role_id(role_id).await.unwrap();
	
	all_permissions.retain(|permission| !current_permissions.contains(permission));
	Ok(all_permissions)
}

pub async fn revoke_permissions_from_role(role_id:i64,permission_ids:Vec<i64>) ->Result<u64, Error> {
	let app_state = init_db();
	let roles = &app_state.await.context.roles;
	for permission_id in permission_ids.iter() {
		roles.revoke_permission_from_role(role_id,*permission_id).await.unwrap();
	}
	Ok(0)
}

pub async fn search_roles_by_fields(role_query_request:RoleQueryRequest) ->Result<Vec<RoleBean>, Error> {
	let app_state = init_db();
	app_state.await.context.roles.search_roles_by_fields(role_query_request).await
}

pub async fn search_roles_by_fields_by_page(role_query_request:RoleQueryRequest) ->Result<Vec<RoleBean>, Error> {
	let app_state = init_db();
	app_state.await.context.roles.search_roles_by_fields_by_page(role_query_request).await
}

pub async fn soft_delete_all_roles(ids:Vec<i64>) ->Result<u64, Error> {
	let app_state = init_db();
	let roles = &app_state.await.context.roles;
	let vecter_iterator = ids.iter();
	for role_id in vecter_iterator {
		let _ = roles.soft_delete_role(*role_id).await;
	}
	Ok(0)
}

pub async fn soft_delete_role(id:i64) ->Result<u64, Error> {
	let app_state = init_db();
	app_state.await.context.roles.soft_delete_role(id).await
}

pub async fn toggle_one_role(id:i64) ->Result<u64, Error> {
	let app_state = init_db();
	let roles = &app_state.await.context.roles;
	let role = roles.find_role_by_id(id).await.unwrap();
	if role.active == false {
		let _ = roles.toggle_role(id).await;
	} else {
		let count = roles.count_active_role_records().await.unwrap();
		if count.count_num > 1 {
			let _ = roles.toggle_role(id).await;
		}
	}
	Ok(0)
}

pub async fn toggle_role(id:i64) ->Result<u64, Error> {
	let app_state = init_db();
	app_state.await.context.roles.toggle_role(id).await
}

pub async fn update_role(role:RoleBean) ->Result<u64, Error> {
	let app_state = init_db();
	app_state.await.context.roles.update_role(role).await
}

pub async fn find_role_indexed_name(name:String) ->Result<String, Error> {
	let mut short_name = name.clone();
	if name.contains("_") && is_digit(name.substring(right_find_under_line(name.clone())+1,name.chars().count()).to_string()) {
		short_name = name.substring(0,right_find_under_line(name.clone())).to_string();
	}

	let app_state = init_db();
	let roles = app_state.await.context.roles.find_role_indexed_name(short_name.clone()).await.unwrap();

	let mut index_num = 1;
	for role in roles {
		let name2 = role.role_name;
		if name2.contains("_") && is_digit(name2.substring(right_find_under_line(name2.clone())+1,name2.chars().count()).to_string()) {
			let index = name2.substring(right_find_under_line(name2.clone())+1,name2.chars().count()).parse::<i32>().unwrap();
			if index >= index_num {
				index_num = index + 1;
			}
		}
	}

	let index_name = short_name.clone() + "_" + &index_num.to_string();
	Ok(index_name)
}

